/**
 * 
 */
package com.abel.repository.impl;

import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.abel.datamodel.type.Applicants;
import com.abel.domain.Application;
import com.abel.domain.DesiredPosition;
import com.abel.domain.HelpfulInformation;
import com.abel.domain.OptionalInformation;
import com.abel.domain.Person;
import com.abel.domain.PersonProfile;
import com.abel.domain.PersonSearchCriteria;
import com.abel.domain.PersonalInformation;
import com.abel.repository.PersonProfileRepository;
import com.abel.repository.exception.NonExistantProfileException;
import com.abel.repository.exception.RepositoryException;
import com.abel.repository.helper.DataConverter;
import com.abel.util.UserSessionLocator;


public  class PersonProfileRepositoryImpl extends BaseRepositoryImpl implements PersonProfileRepository
{
    protected final Log logger = LogFactory.getLog(getClass());
    
    

    /* (non-Javadoc)
     * @see com.abel.repository.PersonalProfileRepository#addPersonalInformation(com.abel.domain.PersonalInformation)
     */
    @Override
    public int addPersonalInformation(PersonalInformation personalInformation)
            throws RepositoryException
    {
        logger.debug("@PersonProfileRepositoryimpl : addPersonalInformation : entered");

        Transaction tx = null;
		Session session = null;
		Applicants applicants = null;
		
		try {
			session = this.getSessionFactory().getCurrentSession();
			tx = session.beginTransaction();
			Person person = UserSessionLocator.getUserSession().getPerson();
			
			//add personalInformation
			applicants = this.setPersonProfile(person, personalInformation);
			applicants.setAplCreateDts(new Date());
			
			//saving personal information
			int personProfileId = Integer.parseInt(((Object)session.save(applicants)).toString());
			tx.commit();
			
			return personProfileId;
		
		} 
		catch (RuntimeException e) {
			logger.info("@PersonProfileRepositoryImpl : addPersonalInformation : exception - while adding personalinformation" + e);
			e.printStackTrace();
			
			if (tx != null && tx.isActive()) {
			
				try {
				
					tx.rollback();
				
				} 
				catch (HibernateException he) {
				
					logger.debug("@PersonProfileRepositoryImpl : addPersonalInformation : exception while rolling back registration" + he);
					he.printStackTrace();
				
				}
			}
			throw new RepositoryException("Exception while adding user=" + personalInformation.getSsn(),e);
		}
    }



    /* (non-Javadoc)
     * @see com.abel.repository.PersonalProfileRepository#updateOptionalInformation(com.abel.domain.OptionalInformation)
     */
    @Override
    public void updateOptionalInformation(
            OptionalInformation optionalInformation) throws RepositoryException {

        logger.debug("@PersonProfileRepositoryimpl : updateOptionalInformation : entered");

        Transaction tx = null;
		Session session = null;
		Applicants applicants = null;
		
		//getting person
		Person person = UserSessionLocator.getUserSession().getPerson();
		
		try {
			session = this.getSessionFactory().getCurrentSession();
			tx = session.beginTransaction();
			
			//update optionalinformation
			applicants = this.setPersonProfile(person, optionalInformation);
			
			//getting personProfileId from UserSession
			applicants.setAplId(person.getApplication().getApplicationId()) ;
			applicants.setAplLastUpdateDts(new Date());
			applicants.setAplLastUpdateId(UserSessionLocator.getUserSession().getAuthPrincipal().getUserName());

			//saving personal information
			session.update(applicants);
			tx.commit();
		
		} 
		catch (RuntimeException e) {

			logger.info("@PersonProfileRepositoryImpl : updateOptionalInformation : exception - while updating optional information" + e);
			e.printStackTrace();
			
			if (tx != null && tx.isActive()) {
			
				try {
				
					tx.rollback();
				
				} 
				catch (HibernateException he) {
				
					logger.debug("@PersonProfileRepositoryImpl : updateOptionalInformation : exception while rolling back update of personal information" + he);
					he.printStackTrace();
				
				}
			}
			throw new RepositoryException("Exception while adding user=" + person.getUserId(), e);
		}
    }

    /* (non-Javadoc)
     * @see com.abel.repository.PersonalProfileRepository#updatePersonalInformation(com.abel.domain.PersonalInformation)
     */
    @Override
    public void updatePersonalInformation(
            PersonalInformation personalInformation) throws RepositoryException {
        
    	logger.debug("@PersonProfileRepositoryimpl : updatePersonalInformation : entered");

        Transaction tx = null;
		Session session = null;
		Applicants applicants = null;
		
		//getting person
		Person person = UserSessionLocator.getUserSession().getPerson();
		
		try {
			session = this.getSessionFactory().getCurrentSession();
			tx = session.beginTransaction();
			
			//update personalInformation
			applicants = this.setPersonProfile(person, personalInformation);
			
			//getting personProfileid from UserSession
			applicants.setAplId(person.getApplication().getApplicationId()) ;
			applicants.setAplLastUpdateDts(new Date());
			applicants.setAplLastUpdateId(UserSessionLocator.getUserSession().getAuthPrincipal().getUserName());

			//saving personal information
			session.update(applicants);
			tx.commit();
		
		} 
		catch (RuntimeException e) {

			logger.info("@PersonProfileRepositoryImpl : updatePersonalInformation : exception - while updating personal information" + e);
			e.printStackTrace();
			
			if (tx != null && tx.isActive()) {
			
				try {
				
					tx.rollback();
				
				} 
				catch (HibernateException he) {
				
					logger.debug("@PersonProfileRepositoryImpl : updatePersonalInformation : exception while rolling back update of personal information" + he);
					he.printStackTrace();
				
				}
			}
			throw new RepositoryException("Exception while adding user=" + person.getUserId(),e);
		}
    }

    
    
    
	/* (non-Javadoc)
	 * @see com.abel.repository.PersonProfileRepository#updateDesiredPosition(com.abel.domain.DesiredPosition)
	 */
	@Override
	public void updateDesiredPosition(DesiredPosition desiredPosition)
			throws RepositoryException {
		
        logger.debug("@PersonProfileRepositoryimpl : updateDesiredPosition : entered");

        Transaction tx = null;
		Session session = null;
		Applicants applicants = null;
		
		//getting person
		Person person = UserSessionLocator.getUserSession().getPerson();
		
		try {
			session = this.getSessionFactory().getCurrentSession();
			tx = session.beginTransaction();
			
			//update updateDesiredPosition
			applicants = this.setPersonProfile(person, desiredPosition);
			
			//getting personProfileId from UserSession
			applicants.setAplId(person.getApplication().getApplicationId()) ;
			applicants.setAplLastUpdateDts(new Date());
			applicants.setAplLastUpdateId(UserSessionLocator.getUserSession().getAuthPrincipal().getUserName());

			//saving personal information
			session.update(applicants);
			tx.commit();
		
		} 
		catch (RuntimeException e) {

			logger.info("@PersonProfileRepositoryImpl : updateDesiredPosition : exception - while updating desired position information" + e);
			e.printStackTrace();
			
			if (tx != null && tx.isActive()) {
			
				try {
				
					tx.rollback();
				
				} 
				catch (HibernateException he) {
				
					logger.debug("@PersonProfileRepositoryImpl : updateDesiredPosition : exception while rolling back update of personal information" + he);
					he.printStackTrace();
				
				}
			}
			throw new RepositoryException("Exception while adding user=" + person.getUserId(), e);
		}
	}



	/* (non-Javadoc)
	 * @see com.abel.repository.PersonProfileRepository#updateHelpfulInformation(com.abel.domain.HelpfulInformation)
	 */
	@Override
	public void updateHelpfulInformation(HelpfulInformation helpfulInformation)
			throws RepositoryException {

        logger.debug("@PersonProfileRepositoryimpl : updateHelpfulInformation : entered");

        Transaction tx = null;
		Session session = null;
		Applicants applicants = null;
		
		//getting person
		Person person = UserSessionLocator.getUserSession().getPerson();
		
		try {
			session = this.getSessionFactory().getCurrentSession();
			tx = session.beginTransaction();
			
			//update updateDesiredPosition
			applicants = this.setPersonProfile(person, helpfulInformation);
			
			//getting personProfileId from UserSession
			applicants.setAplId(person.getApplication().getApplicationId()) ;
			applicants.setAplLastUpdateDts(new Date());
			applicants.setAplLastUpdateId(UserSessionLocator.getUserSession().getAuthPrincipal().getUserName());

			//saving personal information
			session.update(applicants);
			tx.commit();
		
		} 
		catch (RuntimeException e) {

			logger.info("@PersonProfileRepositoryImpl : updateHelpfulInformation : exception - while updating helpful information" + e);
			e.printStackTrace();
			
			if (tx != null && tx.isActive()) {
			
				try {
				
					tx.rollback();
				
				} 
				catch (HibernateException he) {
				
					logger.debug("@PersonProfileRepositoryImpl : updateHelpfulInformation : exception while rolling back update of helpful information" + he);
					he.printStackTrace();
				
				}
			}
			throw new RepositoryException("Exception while adding user=" + person.getUserId(), e);
		}
	}


	@Override
	public PersonProfile getPersonProfile(PersonSearchCriteria criteria) 
		throws RepositoryException, NonExistantProfileException {
		
		logger.debug("@PersonProfileRepositoryImpl : getPersonProfile : entered");
		
		Person person = UserSessionLocator.getUserSession().getPerson();
		
		Transaction tx = null;
		Session session = null;
				
		try {
		
			session = this.getSessionFactory().getCurrentSession();
			tx = session.beginTransaction();
			
			@SuppressWarnings("unchecked")
			List<Applicants> applicantsList = session.getNamedQuery("getPersonProfile").
				setParameter("userId", criteria.getUserId()).list();
			tx.commit();

			if (applicantsList.size() == 0) {
				throw new NonExistantProfileException("Profile does not exist for user id  " + criteria.getUserId());
			}
			
			Applicants applicants = applicantsList.get(0);
			person.getApplication().setApplicationId(applicants.getAplId());
			
			//convert applicants to domain objects
			PersonProfile personProfile = new DataConverter().convertApplicantsToPersonProfile(applicants);
			
			return personProfile;
		} 
		catch (RuntimeException e) {
			
			e.printStackTrace();
			
			if (tx != null && tx.isActive()) {
			
				try {
				
					tx.rollback();
				
				}
				catch (HibernateException he) {
				
					logger.debug("@PersonProfileRepositoryImpl : getPersonProfile : exception while rolling back getting applicants exception " + he);
					he.printStackTrace();
				
				}
			}
			throw new RepositoryException("Exception while getting applicants " + criteria.getUserId(),e);
		}
	}
	
	
	private Applicants setPersonProfile(Person person, Object updateObject) 
		throws RepositoryException{
		
		Applicants applicants = new Applicants();
		
		//set userid
		
		
		int userId = person.getUserId();
		
		if (userId <= 0) {
			throw new RepositoryException("Cannot add personal information. UserId in authPrincipal is " + userId);
		}
		
		applicants.setUserId(userId);
		
		Application application = person.getApplication();
		
		//set from PersonalInformation
		PersonalInformation personalInformation = null;
		
		if (updateObject instanceof PersonalInformation) {
			personalInformation = (PersonalInformation)updateObject;
		}
		else {
			personalInformation = application.getPersonProfile().getPersonalInformation();
		}
		if (personalInformation != null) {
			applicants.setAplSsn(personalInformation.getSsn());
			applicants.setAplFirstName(personalInformation.getFirstName());
			applicants.setAplMiddleName(personalInformation.getMiddleName());
			applicants.setAplLastMame(personalInformation.getLastName());
			applicants.setAplAddrLine1(personalInformation.getAddressLine1());
			applicants.setAplAddrLine2(personalInformation.getAddressLine2());
			applicants.setAplCity(personalInformation.getCity());
			applicants.setAplZip(personalInformation.getZip());
			applicants.setAplState(personalInformation.getState());
			applicants.setAplHomePhone(personalInformation.getHomePhone());
			applicants.setAplAlternatePhone(personalInformation.getAlternatePhone());
			applicants.setAplWorkPhone(personalInformation.getWorkPhone());
			applicants.setAplBirthDate(personalInformation.getDateOfBirth());
			applicants.setAplEmergencyName(personalInformation.getEmergencyContact());
			applicants.setAplemergencyPhone(personalInformation.getEmergencyContactPhone());
			applicants.setAplemergencyRelation(personalInformation.getEmergencyContactRelation());
			applicants.setAplCreateDts(personalInformation.getCreateDate());
		}

		//set from OptionalInformation
		OptionalInformation optionalInformation = null;
		
		if (updateObject instanceof OptionalInformation) {
			optionalInformation = (OptionalInformation)updateObject; 
		}
		else {
			optionalInformation = application.getPersonProfile().getOptionalInformation();
		}
		if (optionalInformation != null) {
			applicants.setAplHeight(optionalInformation.getHeight());
			applicants.setAplWeight(optionalInformation.getWeight());
			applicants.setAplMaritalStatus(optionalInformation.getMaritalStatus());
			applicants.setAplChildrenAges(optionalInformation.getChildrensAges());
		}
		
		//set from HelpfulInformation
		HelpfulInformation helpfulInformation = null;
		
		if (updateObject instanceof HelpfulInformation) {
			helpfulInformation = (HelpfulInformation)updateObject; 
		}
		else {
			helpfulInformation = application.getPersonProfile().getHelpfulInformation();
		}
		if (helpfulInformation != null) {
			applicants.setAplCarAccessYn(helpfulInformation.getAccessToCar() == null ? "" : helpfulInformation.getAccessToCar());
			applicants.setAplRelocateYn(helpfulInformation.getWillingToRelocate() == null ? "" : helpfulInformation.getWillingToRelocate());
			applicants.setAplTravelPct(helpfulInformation.getTravelPercentage());
			applicants.setAplTravelYn(helpfulInformation.getWillingToTravel() == null ? "" : helpfulInformation.getWillingToTravel());
			applicants.setAplEmployedYn(helpfulInformation.getEmployed() == null ? "" : helpfulInformation.getEmployed());
		}
		
		//set from DesiredPositions
		DesiredPosition desiredPosition = null;
		
		if (updateObject instanceof DesiredPosition) {
			desiredPosition = (DesiredPosition)updateObject;
		}
		else {
			desiredPosition = application.getPersonProfile().getDesiredPosition();
		}
		if (desiredPosition != null) {
			applicants.setAplPositionDesired1(desiredPosition.getPosition1stDesired());
			applicants.setAplPositionDesired2(desiredPosition.getPosition2ndDesired());
			applicants.setAplSalaryDesired(desiredPosition.getSalaryDesired());
			applicants.setAplMinimumSalary(desiredPosition.getLeastSalaryAccepted());
			applicants.setAplSalaryDesiredMd(desiredPosition.getSalaryMode());
			applicants.setAplMinimumSalaryMd(desiredPosition.getLeastSalaryMode());
		}
		
		return applicants;
		
	}
}
